function BizProcCoordinator(pageId, baseUrl) {
    this.pageId = pageId;
    this.baseUrl = baseUrl + '?';
    this.bizProcs = new Array();
    this.inEvent = false;
    this.afterAjaxEventHandlers = new Array();
    this.beforeAjaxEventHandlers = new Array();
}

BizProcCoordinator.prototype = {
	addAfterAjaxEventHandler: function (handler) {
		this.afterAjaxEventHandlers.push(handler);
	},

	addBeforeAjaxEventHandler: function (handler) {
		this.beforeAjaxEventHandlers.push(handler);
	},

	addBizProc: function (bizProc) {
		this.bizProcs.push(bizProc);
	},

	getBizProc: function (id) {
		for (var i = 0; i < this.bizProcs.length; i++)
			if (this.bizProcs[i].id == id)
				return this.bizProcs[i];
		return null;
	},

	refreshPage: function () {
		window.location.href = window.location.href;
	},

	triggerEvent: function (bizProc, eventInfo, forceSyncRequest) {
		if (this.inEvent) {
			this.lastEvent = [bizProc, eventInfo];
			return; //Blow off event trigger if in an event already!
		}

		var cont = true;
		for (var p = 0; p < this.beforeAjaxEventHandlers.length; p++)
			try {
				var rc = this.beforeAjaxEventHandlers[p](bizProc, eventInfo);
				if (cont && rc == false)
					cont = false;
			} catch (e) {
			}

		if (!cont)
			return;

		this.disabledButtons = new Array();
		if (eventInfo.disableButtons == true) {
			$(".AcBut").each(function (i) {
				if (!this.disabled) {
					bizProcManager.disabledButtons.push(this);
					this.disabled = true;
				}
			});
			$(".AjaxIndi").css("display", "inline");
		}
		this.inEvent = true;
		try {
			var doc = ksg.util.createXmlDoc('<ClientEvent />');
			var docEl = doc.documentElement;
			docEl.setAttribute('bizProcId', bizProc == null ? '' : bizProc.id);
			eventInfo.addState(docEl);
			for (var p = 0; p < this.bizProcs.length; p++)
				this.processBizProc(doc, docEl, this.bizProcs[p]);

			return this.sendRequest(doc, eventInfo, forceSyncRequest);
		}
		catch (e) {
			//alert("error:" + e);
			this.releaseWaitState();
		}
	},

	processBizProc: function (doc, docEl, bizProc) {
		var bizProcEl = doc.createElement('BizProc');
		bizProc.getState(bizProcEl);
		docEl.appendChild(bizProcEl);
	},

	sendRequest: function (doc, eventInfo, forceSyncRequest, attemptNum) {
		var attempt = 1;
		if (attemptNum != null)
			attempt = attemptNum;
		if (attempt > 3) {
			this.releaseWaitState();
			alert("General Failure Communicating With Web Site.");
			return;
		}
		if (doc == null) return;
		var d = ksg.util.createXmlString(doc.documentElement);
		var u = this.baseUrl + 'pi=' + this.pageId + '&RequestType=' + doc.documentElement.getAttribute('event');
		var async = forceSyncRequest ? false : true;
		$.ajax({ type: "POST", async: async,
			url: u,
			data: d,
			processData: false,
			dataType: "xml",
			contentType: "text/xml",
			success: function (doc) { bizProcManager.processWebResponse(doc, eventInfo); if (eventInfo.eventHandler != null) eventInfo.eventHandler(); },
			error: function (a, b, c) {
				setTimeout(function () { bizProcManager.sendRequest(doc, eventInfo, forceSyncRequest, attempt + 1); }, 200);
			}
		});
	},

	releaseWaitState: function () {
		this.inEvent = false;
		for (var i = 0; i < this.disabledButtons.length; i++)
			try { this.disabledButtons[i].disabled = false; } catch (e) { }
		$(".AjaxIndi").css("display", "none");
	},

	processWebResponse: function (doc, eventInfo) {
		if (doc.documentElement != null && doc.documentElement.getAttribute("gotoView") != null) {
			this.inEvent = false; //Needed incase an unload ajax event happens.
			window.location.href = doc.documentElement.getAttribute("gotoView");
		}
		else {
			try {
				var tempBizProcs = new Array();
				var firstLen = this.bizProcs.length;
				for (var pos = 0; pos < this.bizProcs.length; pos++) {
					var process = true;
					for (var p2 = 0; p2 < tempBizProcs.length; p2++) {
						if (tempBizProcs[p2] == this.bizProcs[pos]) {
							process = false;
							break;
						}
					}
					if (process) {
						tempBizProcs.push(this.bizProcs[pos]);
						var bpid = this.bizProcs[pos].id;
						this.bizProcs[pos].processControlStates(doc);
						if (firstLen != this.bizProcs.length) {
							pos = 0;
							firstLen = this.bizProcs.length;
						}
					}
				}
			}
			catch (e) {
				alert("Error:" + e);
			}

			this.releaseWaitState();

			var indEls = doc.selectNodes("//ControlStates/State[@independent = 'true']");
			if (indEls != null)
				for (var i = 0; i < indEls.length; i++) {
					var script = indEls[i].getAttribute("script");
					if (script != null && script != "")
						try { eval(script); } catch (e) { }
				}

			for (var p = 0; p < this.afterAjaxEventHandlers.length; p++)
				try {
					this.afterAjaxEventHandlers[p](doc, eventInfo);
				} catch (e) {
				}

			if (this.lastEvent != null) {
				var l = this.lastEvent;
				this.lastEvent = null;
				this.triggerEvent(l[0], l[1]);
			}
			return (doc.documentElement == null) ? "" : doc.documentElement.getAttribute("curId");
		}
	}
}


function EventInfo(ctlId, eventId, val, eventHandler, disableButtons) {
    this.disableButtons = disableButtons == false ? false : true;
    this.ctlId = ctlId;
    this.eventId = eventId;
    this.val = val;
    this.eventHandler = eventHandler;
}

EventInfo.prototype.addState = function (eventEl) {
    eventEl.setAttribute('event', this.eventId);
    eventEl.setAttribute('id', this.ctlId);
    if (this.val != null)
        eventEl.setAttribute('value', this.val);
}
function ClientBizProc(id) {
    this.id = id;
    this.ClientControls = new Array();
    bizProcManager.addBizProc(this);
}

ClientBizProc.prototype.addClientControl = function (ctl) {
    for (var pos = 0; pos < this.ClientControls.length; pos++)
        if (this.ClientControls[pos].id == ctl.id) {
            this.ClientControls[pos] = ctl;
            return;
        }
    this.ClientControls[this.ClientControls.length] = ctl;
}

ClientBizProc.prototype.triggerEvent = function (ctlId, eventId, val, eventHandler, disableButtons) {
    try {
        if (ctlId == null)
            ctlId = this.id;
        bizProcManager.triggerEvent(this, new EventInfo(ctlId, eventId, val, eventHandler, disableButtons));
    }
    catch (e) { }
}

ClientBizProc.prototype.getState = function (bizProcEl) {
    bizProcEl.setAttribute('id', this.id);
    this.insertControlStates(bizProcEl.ownerDocument, bizProcEl);
}

ClientBizProc.prototype.processControlStates = function (doc) {
    for (var pos = 0; pos < this.ClientControls.length; pos++) {
        var clientCtl = this.ClientControls[pos];
        var clientId = clientCtl.id;
        if (clientCtl.dhtmlObj != null) {
            if (clientId == null || clientId == '')
                clientId = clientCtl.dhtmlObj.id;
            var stateEl = doc.selectSingleNode("//ControlStates/State[@id = '" + clientId + "']");
            if (stateEl != null && clientCtl.setState != null)
                clientCtl.setState(stateEl);
        }
    }
}

ClientBizProc.prototype.insertControlStates = function (doc, bizProcEl) {
    var states = doc.createElement('ControlStates');
    bizProcEl.appendChild(states);
    for (var pos = 0; pos < this.ClientControls.length; pos++) {
        var clientCtl = this.ClientControls[pos];
        if (clientCtl.getState != null && clientCtl.dhtmlObj != null) {
            var stateEl = doc.createElement('State');
            var clientId = clientCtl.id;
            if (clientId == null || clientId == '')
                clientId = clientCtl.dhtmlObj.id;
            stateEl.setAttribute('id', clientId);
            this.ClientControls[pos].getState(stateEl);
            states.appendChild(stateEl);
        }
    }
}

function ClientControl(dhtmlObj, setStateFun, getStateFun, showBizObjFun, updateBizObjFun) {
    this.dhtmlObj = dhtmlObj;
    this.setState = setStateFun;
    this.getState = getStateFun;
    this.showBizObj = showBizObjFun;
    this.updateBizObj = updateBizObjFun;
    if (dhtmlObj != null)
        this.id = dhtmlObj.id;
}

